package org.sdnstproject.interlayer.OF13Protocal;

import java.util.HashMap;

import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

/*OFPortStatus默认值:OFPortStatusVer13(xid=0, reason=DELETE, 
 * desc=OFPortDescVer13(portNo=2, hwAddr=6e:c1:95:1f:18:58, name=s1-eth2, config=[], 
 * state=[], curr=[PF_10GB_FD, PF_COPPER], advertised=[], supported=[], peer=[], 
 * currSpeed=10000000, maxSpeed=0))
 * */

/**{@code FuPortStatus}:FuPortStatus消息类，功能:根据byte数组构造FuPortStatus消息对象，即：解析FuPortStatus、
 * 默认构造FuPortStatus消息、任意设置修改字段值等.
 * */
public class FuPortStatus {
	private static final Logger log = LoggerFactory.getLogger(FuPortStatus.class);
    /**version 类型:byte 默认值: 1.3*/
    public byte version = 4;
    /**type 类型:byte 默认值: 12*/
    public byte type = 12;
    /**length 类型:short 默认值: 80(0x50)*/
    public short length = 80;
    /**xid 类型:long 默认值: 0x0L*/
    public long xid = 0x0L;
    /**reason 类型:byte 默认值: 1*/
    public byte reason = 1;
    /**desc 类型:OFPortDesc 默认值: OFPortDesc的默认值*/
    public FuPortDesc desc = new FuPortDesc();

    public FuPortStatus() {
    	
    }
    /**根据ByteBuf来构造OFPortStatus,即read from ByteBuf.*/
    public FuPortStatus(ByteBuf bb) {
        // fixed value property version == 4
        this.version = bb.readByte();
        // fixed value property type == 12
        this.type = bb.readByte();
        if(type != (byte) 0xc)
            log.info("Wrong type: Expected=OFType.PORT_STATUS(12), got="+type);
        this.length = bb.readShort();
        this.xid = U32.f(bb.readInt());
        this.reason = bb.readByte();
        // pad: 7 bytes
        bb.skipBytes(7);
        FuPortDesc desc = new FuPortDesc(bb);
    }
    
    public FuPortStatus(byte version, short length, long xid, byte reason, FuPortDesc desc) {
        this.version = version;
        this.length = length;
    	this.xid = xid;
        this.reason = reason;
        this.desc = desc;
    }
    
    public FuPortStatus setField(String field, String value) throws NumberFormatException{
    	switch (field) {
			case "version":
				this.setVersion(Byte.parseByte(value));
				break;
			case "type":
				this.setType(Byte.parseByte(value));
				break;
			case "length":
				this.setLength(Short.parseShort(value));
				break;
			case "xid":
				this.setXid(Long.parseLong(value));
				break;
			case "reason":
				this.setReason(Byte.parseByte(value));
				break;
			case "port_no":
				this.setDesc(this.desc.setPortNo(Integer.parseInt(value)));
				break;
			case "hw_addr":
				this.setDesc(this.desc.setHwAddr(Long.parseLong(value)));
				break;
			case "name":
				this.setDesc(this.desc.setName(value));
				break;
			case "config":
				this.setDesc(this.desc.setConfig(Integer.parseInt(value)));
				break;
			case "state":
				this.setDesc(this.desc.setState(Integer.parseInt(value)));
				break;
			case "curr":
				this.setDesc(this.desc.setCurr(Integer.parseInt(value)));
				break;
			case "advertised":
				this.setDesc(this.desc.setAdvertised(Integer.parseInt(value)));
				break;
			case "supported":
				this.setDesc(this.desc.setSupported(Integer.parseInt(value)));
				break;
			case "peer":
				this.setDesc(this.desc.setPeer(Integer.parseInt(value)));
				break;
			case "curr_speed":
				this.setDesc(this.desc.setCurrSpeed(Long.parseLong(value)));
				break;
			case "max_speed":
				this.setDesc(this.desc.setMaxSpeed(Long.parseLong(value)));
				break;
		}
    	return this;
    }
    /**记录OFPortStatus字段和其类型映射*/
    public static HashMap<String, String> portStatusMsgFields = new HashMap<String, String>() {
		{
			put("version","byte");
			put("type","byte");
			put("length","short");
			put("xid","long");
			put("reason","byte");
			put("port_no","int");
			put("hw_addr","long");
			put("name","String");
			put("config","int");
			put("state","int");
			put("curr","int");
			put("advertised","int");
			put("supported","int");
			put("peer","int"); 
			put("curr_speed","long");
			put("max_speed","long");
		}
	};
	
	public FuPortStatus setVersion(byte version) {
		this.version = version;
		return this;
	}
	public FuPortStatus setType(byte type) {
		this.type = type;
		return this;
	}
	public FuPortStatus setLength(short length) {
		this.length = length;
		return this;
	}
	public FuPortStatus setXid(long xid) {
		this.xid = xid;
		return this;
	}
	public FuPortStatus setReason(byte reason) {
		this.reason = reason;
		return this;
	}
	public FuPortStatus setDesc(FuPortDesc desc) {
		this.desc = desc;
		return this;
	}
	/**将OFPortDesc对象写入ByteBuf*/
	public void write(ByteBuf bb, FuPortStatus message) {
        // fixed value property version = 4
        bb.writeByte(message.version);
        // fixed value property type = 12
        bb.writeByte((byte) 0xc);
        // fixed value property length = 80
        bb.writeShort(message.length);
        bb.writeInt(U32.t(message.xid));
        bb.writeByte(message.reason);
        // pad: 7 bytes
        bb.writeZero(7);
        message.desc.writeTo(bb);
    }
	/**将OFPortDesc对象写入ByteBuf*/
	public void writeTo(ByteBuf bb) {
        // fixed value property version = 4
        bb.writeByte(this.version);
        // fixed value property type = 12
        bb.writeByte((byte) 0xc);
        // fixed value property length = 80
        bb.writeShort(this.length);
        bb.writeInt(U32.t(this.xid));
        bb.writeByte(this.reason);
        // pad: 7 bytes
        bb.writeZero(7);
        this.desc.writeTo(bb);
    }
	
	public ByteBuf writeTo() {
		ByteBuf bb = Unpooled.directBuffer();
        // fixed value property version = 4
        bb.writeByte(this.version);
        // fixed value property type = 12
        bb.writeByte((byte) 0xc);
        // fixed value property length = 80
        bb.writeShort(this.length);
        bb.writeInt(U32.t(this.xid));
        bb.writeByte(this.reason);
        // pad: 7 bytes
        bb.writeZero(7);
        this.desc.writeTo(bb);
        return bb;
    }
	
	@Override
    public String toString() {
        StringBuilder b = new StringBuilder("OFPortStatusVer13(");
        b.append("version=").append(version);
        b.append(", ");
        b.append("type=").append(type);
        b.append(", ");
        b.append("length=").append(length);
        b.append(", ");
        b.append("xid=").append(xid);
        b.append(", ");
        b.append("reason=").append(reason);
        b.append(", ");
        b.append("desc=").append(desc);
        b.append(")");
        return b.toString();
    }

}
